package com.hsd.znsh.service.impl;

import com.hsd.znsh.converter.SensorGroupConverter;
import com.hsd.znsh.entity.*;
import com.hsd.znsh.enums.DeletedStatusEnum;
import com.hsd.znsh.enums.ResultEnum;
import com.hsd.znsh.enums.SensorGroupTypeEnum;
import com.hsd.znsh.exception.ZnshException;
import com.hsd.znsh.pojo.output.SensorGroupVO;
import com.hsd.znsh.pojo.query.SensorGroupQuery;
import com.hsd.znsh.repository.*;
import com.hsd.znsh.service.SensorGroupService;
import com.hsd.znsh.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;

/*
 * @auther: wangjiacai
 *
 * @create: 2018-04-25 14:48:27
 */
@Service
public class SensorGroupServiceImpl extends BaseServiceImpl implements SensorGroupService {

    @Autowired
    private SensorGroupRepository sensorGroupRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserSensorGroupRepository userSensorGroupRepository;

    @Autowired
    private SensorDataRepository sensorDataRepository;

    @Autowired
    private SensorRepository sensorRepository;

    @Autowired
    private SensorTypePropertyRepository sensorTypePropertyRepository;

    @Autowired
    private PropertyRepository propertyRepository;


    @Override
    public List<SensorGroupVO> getSensorGroupList(Pageable pageable, SensorGroupQuery sensorGroupQuery,Integer userId) {
        if(userId!=null) sensorGroupQuery.setCreateUserId(userId);
        List<SensorGroup> list=this.find(HqlUtil.getQueryHql(sensorGroupQuery),sensorGroupQuery,pageable);
        return SensorGroupConverter.converterToSensorGroupVOList(list,userRepository);
    }


    @Override
    public long getSensorGroupListTotalPages(SensorGroupQuery sensorGroupQuery,Integer userId) {
        if(userId!=null) sensorGroupQuery.setCreateUserId(userId);
        return this.count(HqlUtil.getCountHql(sensorGroupQuery),sensorGroupQuery);
    }


    @Override
    public SensorGroupVO getSensorGroupInfo(Integer id) {
        SensorGroup sensorGroup=sensorGroupRepository.findOne(id);
        return SensorGroupConverter.converterToSensorGroupVO(sensorGroup,userRepository);
    }

    @Override
    public SensorGroup addSensorGroup(SensorGroup sensorGroup) {
        validAddSensorGroup(sensorGroup);
        if(SecurityUtil.hasRole("ROLE_BACKGROUND_MANAGER")){
            sensorGroup.setCreateUserId(SecurityUtil.getUserId());
        }
        return sensorGroupRepository.save(sensorGroup);
    }

    @Override
    public SensorGroup updateSensorGroup(SensorGroup sensorGroup) {
        validUpdateSensorGroup(sensorGroup);
        SensorGroup target=sensorGroupRepository.findOne(sensorGroup.getId());
        BeanUtil.copyPropertiesIgnoreNull(sensorGroup,target);
        if(SecurityUtil.hasRole("ROLE_BACKGROUND_MANAGER")){
            target.setCreateUserId(SecurityUtil.getUserId());
        }
        return sensorGroupRepository.save(target);
    }

    private void validAddSensorGroup(SensorGroup sensorGroup){
        SensorGroup sensorGroup1=sensorGroupRepository.findBySensorGroupName(sensorGroup.getSensorGroupName());
        if(sensorGroup1!=null) throw new ZnshException(ResultEnum.SENSOR_GROUP_NAME_EXITS);
        initSensorGroup(sensorGroup);
    }

    private void validUpdateSensorGroup(SensorGroup sensorGroup){
        SensorGroup sensorGroup1=sensorGroupRepository.findBySensorGroupName(sensorGroup.getSensorGroupName());
        if(sensorGroup1!=null&&sensorGroup.getId()!=sensorGroup1.getId()) throw new ZnshException(ResultEnum.SENSOR_GROUP_NAME_EXITS);
        initSensorGroup(sensorGroup);
    }

    private void initSensorGroup(SensorGroup sensorGroup){
        if(StringUtils.isEmpty(sensorGroup.getThSn())){
            sensorGroup.setThSn(null);
        }else{
            if(sensorRepository.findBySensorSn(sensorGroup.getThSn())==null){
                throw new ZnshException(ResultEnum.TH_SN_NOT_EXITS);
            }
        }
        if(StringUtils.isEmpty(sensorGroup.getCo2Sn())){
            sensorGroup.setCo2Sn(null);
        }else{
            if(sensorRepository.findBySensorSn(sensorGroup.getCo2Sn())==null){
                throw new ZnshException(ResultEnum.CO2_SN_NOT_EXITS);
            }
        }
        if(StringUtils.isEmpty(sensorGroup.getLightSn())){
            sensorGroup.setLightSn(null);
        }else{
            if(sensorRepository.findBySensorSn(sensorGroup.getLightSn())==null){
                throw new ZnshException(ResultEnum.LIGHT_SN_NOT_EXITS);
            }
        }
        if(StringUtils.isEmpty(sensorGroup.getWaterSn())){
            sensorGroup.setWaterSn(null);
        }else{
            if(sensorRepository.findBySensorSn(sensorGroup.getWaterSn())==null){
                throw new ZnshException(ResultEnum.WATER_EC_SN_NOT_EXITS);
            }
        }
    }

    @Override
    public void deleteSensorGroup(Integer id) {
        userSensorGroupRepository.deleteBySensorGroupId(id);
        sensorGroupRepository.delete(id);
    }

    @Override
    public List<SensorGroup> getSensorGroupList() {
        return sensorGroupRepository.findBySensorGroupType(SensorGroupTypeEnum.WSD.getCode());
    }

    @Override
    public List<SensorGroup> getUserSensorGroupList(Integer userId) {
        List<Integer> sensorGroupIds=userSensorGroupRepository.findSensorGroupIdListByUserId(userId);
        return sensorGroupRepository.findBySensorGroupTypeAndIdIn(SensorGroupTypeEnum.WSD.getCode(),sensorGroupIds);
    }

    @Override
    public List<SensorGroup> getECList() {
        return sensorGroupRepository.findBySensorGroupType(SensorGroupTypeEnum.EC.getCode());
    }

    @Override
    public List<SensorGroup> getUserECList(Integer userId) {
        List<Integer> sensorGroupIds=userSensorGroupRepository.findSensorGroupIdListByUserId(userId);
        return sensorGroupRepository.findBySensorGroupTypeAndIdIn(SensorGroupTypeEnum.EC.getCode(),sensorGroupIds);
    }

    @Override
    public List<Map<String,Object>> findSensorData(Integer sensorGroupId, String property) {
        SensorGroup sensorGroup=sensorGroupRepository.findOne(sensorGroupId);
        String sensorSn=(String)BeanUtil.getPropertyValue(sensorGroup,property);
        Sensor sensor=sensorRepository.findBySensorSn(sensorSn);
        if(sensor==null) return new ArrayList<>();
        List<Integer> propertyIds=sensorTypePropertyRepository.findPropertyIdListBySensorTypeId(
                sensor.getSensorTypeId());
        List<Property> properties=propertyRepository.findByIdInOrderById(propertyIds);
        List<Map<String,Object>> list=new ArrayList<>();
        for(Property p:properties){
            SensorData sensorData=sensorDataRepository.findBySensorSnAndTimeAndPropertyId(
                    sensorSn,sensor.getTime(),p.getId());
            Map map=BeanUtil.objectToMap(sensorData);
            map.putAll(BeanUtil.objectToMap(p));
            list.add(map);
        }
        return list;
    }

    @Override
    public List<SensorData> findHistorySensorData(Integer sensorGroupId,Integer totalTime,
                                                          String property,Integer bh) {
        SensorGroup sensorGroup=sensorGroupRepository.findOne(sensorGroupId);
        String sensorSn=(String)BeanUtil.getPropertyValue(sensorGroup,property);
        Sensor sensor=sensorRepository.findBySensorSn(sensorSn);
        if(sensor==null) return new ArrayList<>();
        SensorTypeProperty sensorTypeProperty=sensorTypePropertyRepository.findBySensorTypeIdAndBh(
                sensor.getSensorTypeId(),bh);

        Property p=propertyRepository.findOne(sensorTypeProperty.getPropertyId());
        return sensorDataRepository.findBySensorSnAndTimeGreaterThanEqualAndPropertyIdOrderByTimeAsc(
                sensorSn,DateUtil.getPrevDay(totalTime),p.getId());
    }
}
